import store from "@/store";
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
import { ElMessage } from "element-plus";
import { serverConfig } from "./config";

// TODO 加入便捷方法
type DataList = {
    item: any[]
    total: number
    lastPage: number
}

type Response = {
    code: number
    msg: string
    data: any | DataList
}

type elkErr = {
    error: {
        reason: string
    }
}

type elkResp = {
    hits: {
        hits: any[]
    }
}

const nilAxiosInstance: AxiosInstance = axios.create({
    baseURL: serverConfig.baseURL,
    timeout: serverConfig.timeout,
    withCredentials: false // 跨域请求是否需要携带 cookie
})
const defAxiosInstance: AxiosInstance = axios.create({
    baseURL: serverConfig.baseURL,
    timeout: serverConfig.timeout,
    withCredentials: false
})
const elkAxiosInstance: AxiosInstance = axios.create({
    baseURL: serverConfig.baseURL,
    timeout: serverConfig.timeout,
    withCredentials: false
})

// nil 请求拦截
const nilReqIC = (config: AxiosRequestConfig<any>) => {
    if (config.headers!["content-type"] == undefined) {
        config.headers!["content-type"] = "application/json"
    } else if(config.headers!["Content-Type"] === 'application/x-www-form-urlencoded') {
        config.data = JSON.stringify(config.data) // 序列化表单数据
    }

    return config
}
// def 请求拦截
const defReqIC = (config: AxiosRequestConfig<any>) => {
    config.headers!["Authorization"] = store.getters.jwt
    
    if (config.headers!["content-type"] == undefined) {
        config.headers!["content-type"] = "application/json"
    } else if(config.headers!["Content-Type"] === 'application/x-www-form-urlencoded') {
        config.data = JSON.stringify(config.data) // 序列化表单数据
    }

    return config
}
// elk 请求拦截
const elkReqIC = (config: AxiosRequestConfig<any>) => {
    if (config.headers!["content-type"] == undefined) {
        config.headers!["content-type"] = "application/json"
    } else if(config.headers!["Content-Type"] === 'application/x-www-form-urlencoded') {
        config.data = JSON.stringify(config.data) // 序列化表单数据
    }
    config.auth = {
        username: "ctp_guest",
        password: "ctp_pass"
    }

    return config
}
// 请求错误拦截
const reqICErr = (err: any) => {
    return Promise.reject(err)
}
// 自定义结构响应拦截
const cstRespIC = (res: AxiosResponse<Response, any>) => {
    if (res.data.code != 1200 && res.data.code != 1201) {
        ElMessage({
            showClose: true,
            message: res.data.msg,
            type: "error"
        })
    }

    return res
}
// elastic结构响应拦截
const elkRespIC = (res: AxiosResponse<elkErr|elkResp, any>) => {
    if ((res.data as elkErr).error != null) {
        ElMessage({
            showClose: true,
            message: (res.data as elkErr).error.reason,
            type: "error"
        })
        let resS:elkResp = {
            hits: {
                hits: []
            }
        }
        return resS
    }

    return res.data
}
// 响应错误拦截
const respICErr = (err: AxiosError<Response, any>) => {
    let message: string
    if (err && err.response) {
        switch (err.response.status) {
        case 302:
            message = "接口重定向了！"
            break
        case 400:
            message = "参数不正确！"
            break
        case 401:
            message = "您未登录，或者登录已经超时，请先登录！"
            break
        case 403:
            message = "您没有权限操作！"
            break
        case 404:
            message = "请求地址出错: "+ err.response.config.url // 一般不会
            break
        case 408:
            message = "请求超时！"
            break
        case 409:
            message = "系统已存在相同数据！"
            break
        case 500:
            message = "服务器内部错误！"
            break
        case 501:
            message = "服务未实现！"
            break
        case 502:
            message = "网关错误！"
            break
        case 503:
            message = "服务不可用！"
            break
        case 504:
            message = "服务暂时无法访问，请稍后再试！"
            break
        case 505:
            message = "HTTP 版本不受支持！"
            break
        default:
            message = "异常问题，请联系管理员！"
            break
        }
    } else {
        switch (err.code) {
        case 'ECONNABORTED':
            message = "连接超时，请检查网络！"
            break
        default:
            message = "连接有误，请检查网络！"
            break
        }
    }
    ElMessage({
      showClose: true,
      message: message,
      type: "error",
    })

    return Promise.reject(err)
}

nilAxiosInstance.interceptors.request.use(nilReqIC, reqICErr)
nilAxiosInstance.interceptors.response.use(cstRespIC, respICErr)

defAxiosInstance.interceptors.request.use(defReqIC, reqICErr)
defAxiosInstance.interceptors.response.use(cstRespIC, respICErr)

elkAxiosInstance.interceptors.request.use(elkReqIC, reqICErr)
elkAxiosInstance.interceptors.response.use(elkRespIC, respICErr)

export {nilAxiosInstance, defAxiosInstance, elkAxiosInstance}
